﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EntryEngine;
using EntryEngine.Network;
using EntryEngine.Cmdline;
using System.Net;
using EntryEngine.Serialize;
using System.IO;
using EntryEngineServer;
using System.Xml.Linq;

namespace Server
{
    [CMD]
    public interface ICmd
    {
        /// <summary>设置数据库</summary>
        /// <param name="dbconn">数据库连接字符串</param>
        /// <param name="dbname">数据库名称</param>
        /// <param name="isRebuild">是否自动更新数据库结构</param>
        void SetDatabase(string dbconn, string dbname, bool isRebuild);

        /// <summary>线上采用运维管理工具开启服务时，应调用此方法来将日志写入运维管理工具</summary>
        void LoggerToManager();

        /// <summary>启动服务器</summary>
        /// <param name="port">服务器端口</param>
        void Launch(ushort port);
    }
    partial class Service : ProxyHttpAsync, ICmd
    {
        ParallelRouter<HttpListenerContext> router = new ParallelRouter<HttpListenerContext>();
        ParallelJsonHttpService[] nonLogin = new ParallelJsonHttpService[8];
        ParallelJsonHttpService[] doneLogin = new ParallelJsonHttpService[8];

        protected override Link InternalAccept(HttpListenerContext context)
        {
            router.Route(context);
            return null;
        }
        protected override IEnumerator<LoginResult> Login(Link link)
        {
            throw new NotImplementedException();
        }
        protected override void OnUpdate(GameTime time)
        {
            // 每帧执行的业务逻辑
        }

        object pluginDB;
        IPlugin ipluginAPI;
        Dictionary<string, object> pluginAPIObject;

        void ICmd.SetDatabase(string dbconn, string dbname, bool isRebuild)
        {
            PluginManager.Watch("Database.dll", (plugin) =>
            {
                pluginDB = plugin.Inject(dbconn, dbname, isRebuild);
            });
        }
        void ICmd.LoggerToManager()
        {
            if (_LOG._Logger is LoggerFile)
            {
                Logger logger = new Logger();
                logger.Colors.Remove(0);
                ((LoggerFile)_LOG._Logger).Base = logger;
            }
        }
        void ICmd.Launch(ushort port)
        {
            string prefix;
            if (port == 80)
                prefix = string.Format("http://*/share/");
            else
                prefix = string.Format("http://*:{0}/share/", port);

            _LOG.Info("Lauching \"{0}\"", prefix);

            this.RegistServeiceUriPrefix(prefix);
            this.Initialize(IPAddress.Loopback, port);

            {
                // 处理登录和注册
                for (int i = 0; i < nonLogin.Length; i++)
                {
                    nonLogin[i] = new ParallelJsonHttpService();
                }
                router.AddRouter(c =>
                {
                    string token = c.Request.Headers["Authorization"];
                    if (string.IsNullOrEmpty(token))
                    {
                        // 注册时，必须队列执行（否则可能创建多个相同账号），所以必须分配到相同线程
                        if (c.Request.Url.LocalPath == "/Action/1/Register")
                            return 1024;
                        // 支付怕超出库存，没有库存时可直接退款
                        else if (c.Request.Url.LocalPath == "/Action/1/WeChatPayCallback" || c.Request.Url.LocalPath == "/Action/1/WeChatRefundCallback")
                            return 1025;
                        else if (c.Request.Url.LocalPath == "/Action/1/AlipayCallback")
                            return 1026;
                        // 随机分配线程
                        return _RANDOM.Next(0, 1000);
                    }
                    else
                        // 不处理
                        return -1;
                }, nonLogin);
            }
            {
                // 处理登录后的请求
                doneLogin = new ParallelJsonHttpService[8];
                for (int i = 0; i < doneLogin.Length; i++)
                {
                    doneLogin[i] = new ParallelJsonHttpService();
                }
                router.AddRouter(c =>
                {
                    string token = c.Request.Headers["Authorization"];
                    if (string.IsNullOrEmpty(token))
                    {
                        c.Response.StatusCode = 403;
                        c.Response.Close();
                        return -1;
                    }
                    // 按用户分配线程
                    return Math.Abs(token.GetHashCode());
                }, doneLogin);
            }

            PluginManager.Watch("API.dll", (plugin) =>
            {
                if (ipluginAPI != null)
                    _S<CmdlineGate>.Value.ClearCommand(ipluginAPI);
                pluginAPIObject = (Dictionary<string, object>)plugin.Inject(pluginDB, pluginAPIObject);
                var pluginAPI = (Func<Func<HttpListenerContext>, StubHttp[]>)pluginAPIObject["Stubs"];
                foreach (var item in nonLogin)
                    item.HotFixAgent(pluginAPI);
                foreach (var item in doneLogin)
                    item.HotFixAgent(pluginAPI);
                ipluginAPI = plugin;
                _S<CmdlineGate>.Value.AppendCommand(plugin);
            });

            // 正式环境通知管理器服务器已正常开启
            _LOG.Write(255, string.Empty);
        }
    }
}
